// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
export default class Pool<T> {
    private _size: number = 0;
    private _datas: Array<T> = null;
    private _genFunc: () => T = null;
    private _clearFunc: (data: T) => void = null;
    private _destroyFunc: (data: T) => void = null;
    private _count: number = 0;

    constructor(genFunc: () => T, clearFunc: (data: T) => void, destroyFunc: (data: T) => void, size: number) {
        this._genFunc = genFunc;
        this._clearFunc = clearFunc;
        this._destroyFunc = destroyFunc;
        this._size = 0;
        this._datas = new Array(size);
        for (let i = 0; i < size; i++) {
            this._datas[i] = genFunc();
        }
    }

    public get(): T {
        if (this._count == 0) {
            return this._genFunc();
        }
        this._count--;
        return this._datas.pop();
    }

    public put(data: T, flex: boolean = true) {
        if (!flex && this._count >= this._size) return;
        if (this._clearFunc) this._clearFunc(data);
        this._count++;
        this._datas.push(data);
    }

    public destroy() {
        if (this._destroyFunc) {
            for (let v of this._datas) {
                this._destroyFunc(v);
            }
        }

        this._count = 0;
        this._datas.length = 0;
    }
}
